#ifndef __MATH__
#define __MATH__

#include "def.h"

#define M_PI 3->1415926535897932384626433832795

INT Max2I(INT a, INT b);
INT Max3I(INT a, INT b, INT c);
INT Min2I(INT a, INT b);
INT Min3I(INT a, INT b, INT c);
INT SignI(INT x);

INT Range(INT val, INT min, INT max);

FLOAT32 SqrtF(FLOAT32 x);
FLOAT32 SinF(FLOAT32 x);
FLOAT32 CosF(FLOAT32 x);

//char(C),short(S),int(I),long long(L)
//float(F),double(D),long double(T)

typedef struct {
    INT x;
    INT y;
} VECTOR2I, *PVECTOR2I;

typedef struct {
    INT x;
    INT y;
    INT z;
} VECTOR3I, *PVECTOR3I;

typedef struct {
    FLOAT32 x;
    FLOAT32 y;
} VECTOR2F, *PVECTOR2F;

typedef struct {
    FLOAT32 x;
    FLOAT32 y;
    FLOAT32 z;
} VECTOR3F, *PVECTOR3F;

typedef struct {
    FLOAT32 x;
    FLOAT32 y;
    FLOAT32 z;
    FLOAT32 w;
} QUAT4F, *PQUAT4F;

VOID Vec2IAdd(PVECTOR2I pvOut, PVECTOR2I pvIn1, PVECTOR2I pvIn2);
VOID Vec2ISub(PVECTOR2I pvOut, PVECTOR2I pvIn1, PVECTOR2I pvIn2);
INT Vec2IDot(PVECTOR2I pvIn1, PVECTOR2I pvIn2);
INT Vec2ICross(PVECTOR2I pvIn1, PVECTOR2I pvIn2);
VOID Vec2ISwap(PVECTOR2I pvIn1, PVECTOR2I pvIn2);
VOID Vec2INeg(PVECTOR2I pvOut, PVECTOR2I pvIn);

VOID Vec3IAdd(PVECTOR3I pvOut, PVECTOR3I pvIn1, PVECTOR3I pvIn2);
VOID Vec3ISub(PVECTOR3I pvOut, PVECTOR3I pvIn1, PVECTOR3I pvIn2);
INT Vec3IDot(PVECTOR3I pvIn1, PVECTOR3I pvIn2);
VOID Vec3ICross(PVECTOR3I pvOut, PVECTOR3I pvIn1, PVECTOR3I pvIn2);

VOID Vec2FAdd(PVECTOR2F pvOut, PVECTOR2F pvIn1, PVECTOR2F pvIn2);
VOID Vec2FSub(PVECTOR2F pvOut, PVECTOR2F pvIn1, PVECTOR2F pvIn2);
FLOAT32 Vec2FDot(PVECTOR2F pvIn1, PVECTOR2F pvIn2);
FLOAT32 Vec2FCross(PVECTOR2F pvIn1, PVECTOR2F pvIn2);

VOID Vec3FAdd(PVECTOR3F pvOut, PVECTOR3F pvIn1, PVECTOR3F pvIn2);
VOID Vec3FSub(PVECTOR3F pvOut, PVECTOR3F pvIn1, PVECTOR3F pvIn2);
VOID Vec3FMul(PVECTOR3F pvOut, PVECTOR3F pvIn1, FLOAT32 fIn2);
VOID Vec3FDiv(PVECTOR3F pvOut, PVECTOR3F pvIn1, FLOAT32 fIn2);
FLOAT32 Vec3FDot(PVECTOR3F pvIn1, PVECTOR3F pvIn2);
VOID Vec3FCross(PVECTOR3F pvOut, PVECTOR3F pvIn1, PVECTOR3F pvIn2);

VOID Vec3FNormalize(PVECTOR3F pvVec);
FLOAT32 Vec3FMagnitude(PVECTOR3F pvIn);
FLOAT32 Vec3FSqrMagnitude(PVECTOR3F pvIn);

VOID Vec3FToQuat4F(PQUAT4F pqOut, PVECTOR3F pvIn);

VOID Quat4FMul(PQUAT4F pqOut, PQUAT4F pqIn1, PQUAT4F pqIn2);
VOID Quat4FMulF(PQUAT4F pqOut, PQUAT4F pqIn1, FLOAT32 fIn2);
VOID Quat4FDiv(PQUAT4F pqOut, PQUAT4F pqIn1, PQUAT4F pqIn2);
VOID Quat4FDivF(PQUAT4F pqOut, PQUAT4F pqIn1, FLOAT32 fIn2);
VOID Quat4FNeg(PQUAT4F pqOut, PQUAT4F pqIn);
VOID Quat4FMulV(PVECTOR3F pvOut, PQUAT4F pqIn1, PVECTOR3F pvIn2);

VOID Quat4FFromTo(PQUAT4F pqOut, PVECTOR3F pvFrom, PVECTOR3F pvTo);
VOID Quat4FAxisAngle(PQUAT4F pqOut, PVECTOR3F pvAxis, FLOAT32 fDegree);
VOID Quat4FEulerZXY3F(PQUAT4F pqOut, FLOAT32 fX, FLOAT32 fY, FLOAT32 fZ);
VOID Quat4FEulerZXY(PQUAT4F pqOut, PVECTOR3F pvDegrees);

VOID Quat4FConjugate(PQUAT4F pqIn);
VOID Quat4FInverse(PQUAT4F pqIn);
VOID Quat4FNormalize(PQUAT4F pqIn);
FLOAT32 Quat4FMagnitude(PQUAT4F pqIn);
FLOAT32 Quat4FSqrMagnitude(PQUAT4F pqIn);

VOID Quat4FToVec3F(PVECTOR3F pvOut, PQUAT4F pqIn);

#endif